// 文件名：array_span_view.cpp
// 目的：展示 std::span 的零拷贝视图能力：对数组/容器片段执行规范化与相似度计算。
// API：
//   - normalize(std::span<float>)：对缓冲区进行 L1 归一化（各元素除以总和）；
//   - cosineSimilarity(std::span<const float>, std::span<const float>)：计算余弦相似度；
// 用法要点：
//   - std::span 提供对现有连续内存的非拥有视图，避免拷贝；支持子视图 subspan；
//   - 维度不一致时返回 0.0f（简单容错）；范数为 0 时返回 0.0f（避免除零）；
//   - 需要 C++20 支持 <span>。
// 数值注意：
//   - 归一化时若总和为 0 则直接返回；
//   - 浮点误差可能影响相似度计算，可按需加入 eps 保护或使用双精度。

#include <array>
#include <numeric>
#include <span>
#include <cmath>
#include <iostream>

// L1 归一化：将各分量除以总和
void normalize(std::span<float> buffer) {
    float sum = std::accumulate(buffer.begin(), buffer.end(), 0.0f);
    if (sum == 0.0f) return;
    for (auto& v : buffer) {
        v /= sum;
    }
}

// 余弦相似度：dot(a,b) / (||a|| * ||b||)
float cosineSimilarity(std::span<const float> lhs, std::span<const float> rhs) {
    if (lhs.size() != rhs.size()) return 0.0f;
    float dot = 0.0f, normL = 0.0f, normR = 0.0f;
    for (std::size_t i = 0; i < lhs.size(); ++i) {
        dot   += lhs[i] * rhs[i];
        normL += lhs[i] * lhs[i];
        normR += rhs[i] * rhs[i];
    }
    return (normL == 0.0f || normR == 0.0f) ? 0.0f : dot / std::sqrt(normL * normR);
}

int main() {
    std::array<float, 6> featureA = {4.0f, 1.0f, 0.0f, 2.0f, 3.0f, 5.0f};
    std::array<float, 6> featureB = {2.0f, 1.0f, 3.0f, 0.0f, 4.0f, 1.0f};

    normalize(featureA);
    normalize(featureB);

    // 对前 3 维创建子视图
    auto subA = std::span(featureA).subspan(0, 3);
    auto subB = std::span(featureB).subspan(0, 3);

    float sim = cosineSimilarity(subA, subB);
    std::cout << "Cosine similarity (first 3 dims): " << sim << '\n';

    float simAll = cosineSimilarity(featureA, featureB);
    std::cout << "Cosine similarity (all dims): " << simAll << '\n';
    return 0;
}